import { ie, ios } from './browser.js';

export function classTest(cls) {
  return new RegExp('(^|\\s)' + cls + '(?:$|\\s)\\s*');
}

export let rmClass = function (node, cls) {
  let current = node.className;
  let match = classTest(cls).exec(current);
  if (match) {
    let after = current.slice(match.index + match[0].length);
    node.className = current.slice(0, match.index) + (after ? match[1] + after : '');
  }
};

export function removeChildren(e) {
  for (let count = e.childNodes.length; count > 0; --count) e.removeChild(e.firstChild);
  return e;
}

export function removeChildrenAndAdd(parent, e) {
  return removeChildren(parent).appendChild(e);
}

export function elt(tag, content, className, style) {
  let e = document.createElement(tag);
  if (className) e.className = className;
  if (style) e.style.cssText = style;
  if (typeof content == 'string') e.appendChild(document.createTextNode(content));
  else if (content) for (let i = 0; i < content.length; ++i) e.appendChild(content[i]);
  return e;
}
// wrapper for elt, which removes the elt from the accessibility tree
export function eltP(tag, content, className, style) {
  let e = elt(tag, content, className, style);
  e.setAttribute('role', 'presentation');
  return e;
}

export let range;
if (document.createRange)
  range = function (node, start, end, endNode) {
    let r = document.createRange();
    r.setEnd(endNode || node, end);
    r.setStart(node, start);
    return r;
  };
else
  range = function (node, start, end) {
    let r = document.body.createTextRange();
    try {
      r.moveToElementText(node.parentNode);
    } catch (e) {
      return r;
    }
    r.collapse(true);
    r.moveEnd('character', end);
    r.moveStart('character', start);
    return r;
  };

export function contains(parent, child) {
  if (child.nodeType == 3)
    // Android browser always returns false when child is a textnode
    child = child.parentNode;
  if (parent.contains) return parent.contains(child);
  do {
    if (child.nodeType == 11) child = child.host;
    if (child == parent) return true;
  } while ((child = child.parentNode));
}

export function activeElt() {
  // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement.
  // IE < 10 will throw when accessed while the page is loading or in an iframe.
  // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable.
  let activeElement;
  try {
    activeElement = document.activeElement;
  } catch (e) {
    activeElement = document.body || null;
  }
  while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)
    activeElement = activeElement.shadowRoot.activeElement;
  return activeElement;
}

export function addClass(node, cls) {
  let current = node.className;
  if (!classTest(cls).test(current)) node.className += (current ? ' ' : '') + cls;
}
export function joinClasses(a, b) {
  let as = a.split(' ');
  for (let i = 0; i < as.length; i++) if (as[i] && !classTest(as[i]).test(b)) b += ' ' + as[i];
  return b;
}

export let selectInput = function (node) {
  node.select();
};
if (ios)
  // Mobile Safari apparently has a bug where select() is broken.
  selectInput = function (node) {
    node.selectionStart = 0;
    node.selectionEnd = node.value.length;
  };
else if (ie)
  // Suppress mysterious IE10 errors
  selectInput = function (node) {
    try {
      node.select();
    } catch (_e) {}
  };
